package cn.com.css.taxInspection.system.service.impl;

import java.util.List;
import java.util.Random;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.com.css.taxInspection.common.constants.Constants;
import cn.com.css.taxInspection.system.entity.SysRolePermission;
import cn.com.css.taxInspection.system.entity.SysUser;
import cn.com.css.taxInspection.system.entity.SysUserRole;
import cn.com.css.taxInspection.system.service.PermissionService;
import cn.com.css.taxInspection.system.service.RedisService;
import cn.com.css.taxInspection.system.service.RolePermissionService;
import cn.com.css.taxInspection.system.service.RoleService;
import cn.com.css.taxInspection.system.service.UserRoleService;

/**
 * session管理器
 */
@Service
public class HttpSessionService {
    @Resource
    private RedisService redisService;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RolePermissionService rolePermissionService;
    @Resource
    private HttpServletRequest request;
    @Resource
    private PermissionService permissionService;
    @Resource
    private RoleService roleService;
    @Value("${spring.redisToken.key.prefix.userToken}")
    private String userTokenPrefix;
    @Value("${spring.redisToken.key.expire.userToken}")
    private int exire;
    @Value("${spring.redisToken.key.prefix.permissionRefresh}")
    private String redisPermissionRefreshKey;
    @Value("${spring.redisToken.key.expire.permissionRefresh}")
    private Long redisPermissionRefreshExpire;

    public String createTokenAndUser(SysUser user, List<String> roles, List<String> rolesId, Set<String> permissions) {
        // 方便根据id找到redis的key， 修改密码/退出登陆 方便使用
        String token = getRandomToken() + "#" + user.getId();
        JSONObject sessionInfo = new JSONObject();
        sessionInfo.put(Constants.USERID_KEY, user.getId());
        sessionInfo.put(Constants.USERNAME_KEY, user.getUsername());
        sessionInfo.put(Constants.ROLES_KEY, roles);
        sessionInfo.put(Constants.ROLES_ID, rolesId);
        sessionInfo.put(Constants.PERMISSIONS_KEY, permissions);
        sessionInfo.put(Constants.DEPT_ID, user.getDeptId());
        sessionInfo.put(Constants.DEPT_NO, user.getDeptNo());
        sessionInfo.put(Constants.IDENTITY_NO, user.getSwrysfDm());
        sessionInfo.put(Constants.IDENTITY_NAME, user.getRysfmc());
        String key = userTokenPrefix + token;
        // 设置该用户已登录的token
        redisService.setAndExpire(key, sessionInfo.toJSONString(), exire);
        // 登陆后删除权限刷新标志
        redisService.del(redisPermissionRefreshKey + user.getId());
        return token;
    }

    /**
     * 根据token获取userid
     *
     * @param token token
     * @return userid
     */
    public static String getUserIdByToken(String token) {
        if (StringUtils.isBlank(token) || !token.contains("#")) {
            return "";
        } else {
            return token.substring(token.indexOf("#") + 1);
        }
    }

    /**
     * 获取参数中的token
     *
     * @return token
     */
    public String getTokenFromHeader() {
        String token = request.getHeader(Constants.ACCESS_TOKEN);
        // 如果header中不存在token，则从参数中获取token
        if (StringUtils.isBlank(token)) {
            token = request.getParameter(Constants.ACCESS_TOKEN);
        }
        return token;
    }

    /**
     * 获取当前session信息
     *
     * @return session信息
     */
    public JSONObject getCurrentSession() {
        String token = getTokenFromHeader();
        if (null != token) {
            if (redisService.exists(userTokenPrefix + token)) {
                String sessionInfoStr = redisService.get(userTokenPrefix + token);
                return JSON.parseObject(sessionInfoStr);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息
     *
     * @return session信息
     */
    public JSONObject getCurrentSessionNew(String token, String userId) {
//		String token = getTokenFromHeader();
        if (null != token) {
            if (redisService.exists(userTokenPrefix + token + "#" + userId)) {
                String sessionInfoStr = redisService.get(userTokenPrefix + token + "#" + userId);
                return JSON.parseObject(sessionInfoStr);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 username
     *
     * @return username
     */
    public String getCurrentUsername() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.USERNAME_KEY);
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 UserId
     * 获取当前登录人ID
     *
     * @return UserId
     */
    public String getCurrentUserId() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.USERID_KEY);
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 DEPT_NO
     *
     * @return DEPT_NO
     */
    public String getCurrentDeptNo() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.DEPT_NO);
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 DEPT_ID
     * 获取当前登录人税务机关代码
     */
    public String getCurrentDeptId() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.DEPT_ID);
        } else {
            return null;
        }
    }

    /**
     * 获取日志使用的机构编码（部门ID去掉后两位补00）
     * 示例: "123456" → "123400", "A1" → "00", null → null
     */
    public String getLogSwjgDm() {
        // 1. 从session获取部门ID（和getCurrentDeptId()逻辑一致）
        String deptId = null;
        if (getCurrentSession() != null) {
            deptId = getCurrentSession().getString(Constants.DEPT_ID);
        }

        // 2. 如果为空或长度不足2，返回null
        if (deptId == null || deptId.length() < 2) {
            return null;
        }

        // 3. 去掉后两位并补00
        return deptId.substring(0, deptId.length() - 2) + "00";
    }

    /**
     * 获取当前session信息 IDENTITY_NO
     *
     * @return IDENTITY_NO
     */
    public String getCurrentIdentityNo() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.IDENTITY_NO);
        } else {
            return null;
        }
    }


    /**
     * 获取当前session信息 IDENTITY_NAME
     *
     * @return IDENTITY_NAME
     */
    public String getCurrentIdentityName() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.IDENTITY_NAME);
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 Roles_ID
     *
     * @return DEPT_ID
     */
    public String getCurrentRolesId() {
        if (getCurrentSession() != null) {
            return getCurrentSession().getString(Constants.ROLES_ID);
        } else {
            return null;
        }
    }

    /**
     * 获取当前session信息 Roles_ID
     *
     * @return DEPT_ID
     */
    public String getCurrentRolesIdNew(String token, String userId) {
        if (getCurrentSessionNew(token, userId) != null) {
            return getCurrentSessionNew(token, userId).getString(Constants.ROLES_ID);
        } else {
            return null;
        }
    }

    /**
     * 使当前用户的token失效
     */
    public void abortUserByToken() {
        String token = getTokenFromHeader();
        redisService.del(userTokenPrefix + token);
    }

    /**
     * 使所有用户的token失效
     */
    public void abortAllUserByToken() {
        String token = getTokenFromHeader();
        String userId = getUserIdByToken(token);
        redisService.delKeys(userTokenPrefix + "*#" + userId);
    }

    /**
     * 使用户的token失效
     */
    public void abortUserById(String userId) {
        redisService.delKeys(userTokenPrefix + "*#" + userId);
    }

    /**
     * 使多个用户的token失效
     */
    public void abortUserByUserIds(List<String> userIds) {
        if (CollectionUtils.isNotEmpty(userIds)) {
            for (String id : userIds) {
                redisService.delKeys(userTokenPrefix + "*#" + id);
            }

        }
    }

    /**
     * 根据用户id， 刷新redis用户权限
     *
     * @param userId userId
     */
    public void refreshUerId(String userId) {
        Set<String> keys = redisService.keys("#" + userId);
        // 如果修改了角色/权限， 那么刷新权限
        for (String key : keys) {
            JSONObject redisSession = JSON.parseObject(redisService.get(key));

            List<String> roleNames = getRolesByUserId(userId);
            if (roleNames != null && !roleNames.isEmpty()) {
                redisSession.put(Constants.ROLES_KEY, roleNames);
            }
            Set<String> permissions = getPermissionsByUserId(userId);
            redisSession.put(Constants.PERMISSIONS_KEY, permissions);

            Long redisTokenKeyExpire = redisService.getExpire(key);
            // 刷新token绑定的角色权限
            redisService.setAndExpire(key, redisSession.toJSONString(), redisTokenKeyExpire);

        }
    }

    /**
     * 根据角色id， 刷新redis用户权限
     *
     * @param roleId roleId
     */
    public void refreshRolePermission(String roleId) {
        List<Object> userIds = userRoleService.listObjs(
                Wrappers.<SysUserRole>lambdaQuery().select(SysUserRole::getUserId).eq(SysUserRole::getRoleId, roleId));
        ;
        if (!userIds.isEmpty()) {
            for (Object userId : userIds) {
                redisService.setAndExpire(redisPermissionRefreshKey + userId, String.valueOf(userId),
                        redisPermissionRefreshExpire);
            }

        }
    }

    /**
     * 根据权限id， 刷新redis用户权限
     *
     * @param permissionId permissionId
     */
    public void refreshPermission(String permissionId) {
        // 根据权限id，获取所有角色id
        List<Object> roleIds = rolePermissionService.listObjs(Wrappers.<SysRolePermission>lambdaQuery()
                .select(SysRolePermission::getRoleId).eq(SysRolePermission::getPermissionId, permissionId));
        if (!roleIds.isEmpty()) {
            // 根据角色id， 获取关联用户
            List<Object> userIds = userRoleService.listObjs(Wrappers.<SysUserRole>lambdaQuery()
                    .select(SysUserRole::getUserId).in(SysUserRole::getRoleId, roleIds));
            if (!userIds.isEmpty()) {
                // 删除用户redis
                userIds.parallelStream().forEach(userId -> redisService.setAndExpire(redisPermissionRefreshKey + userId,
                        userId.toString(), redisPermissionRefreshExpire));
            }
        }
    }

    /**
     * 生成随机的token
     *
     * @return token
     */
    private String getRandomToken() {
        Random random = new Random();
        StringBuilder randomStr = new StringBuilder();

        // 根据length生成相应长度的随机字符串
        for (int i = 0; i < 32; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";

            // 输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                // 输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                randomStr.append((char) (random.nextInt(26) + temp));
            } else {
                randomStr.append(random.nextInt(10));
            }
        }

        return randomStr.toString();
    }

    private List<String> getRolesByUserId(String userId) {
        return roleService.getRoleNames(userId);
    }

    private Set<String> getPermissionsByUserId(String userId) {
        return permissionService.getPermissionsByUserId(userId);
    }

}
